package org.sanguine.tests.tenderpro.sax;

import org.sanguine.tests.tenderpro.sax.actions.Action;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * Author: Alexey Kuznetsov
 * Date: 20.02.14
 * SVN $Id$
 */
public class ProxyHandler implements ContentHandler {
    Set<Action> handlers = new HashSet<>();

    private void invokeCustomHandlersMethod(String methodName, Object ... params) {
        for (Action handler : handlers) {

            Method[] methods = handler.getClass().getMethods();
            Method method = null;

            for (Method m : methods) {
                if (m.getName().equals(methodName)) {
                    method = m;
                    break;
                }
            }

            if (method == null) throw new java.lang.RuntimeException("Internal error, Action handler method " + methodName
                                                    + " in class " + handler.getClass().getName() + " not found");

            try {
                method.invoke(handler, params);
            } catch (IllegalAccessException e) {
                throw new java.lang.RuntimeException("Internal error, Can't invoke method " + methodName
                        + " of class " + handler.getClass().getName(), e);
            } catch (InvocationTargetException e) {
                throw new java.lang.RuntimeException("Internal error, Can't invoke method  " + methodName
                        + " of class " + handler.getClass().getName(), e);
            }
        }
    }

    @Override
    public void setDocumentLocator(Locator locator) {
        invokeCustomHandlersMethod("setDocumentLocator", locator);
    }

    @Override
    public void startDocument() throws SAXException {
        invokeCustomHandlersMethod("startDocument");
    }

    @Override
    public void endDocument() throws SAXException {
        invokeCustomHandlersMethod("endDocument");
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        invokeCustomHandlersMethod("startPrefixMapping", uri);
    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException {
        invokeCustomHandlersMethod("endPrefixMapping", prefix);
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        invokeCustomHandlersMethod("startElement", uri, localName, qName, atts);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        invokeCustomHandlersMethod("endElement", uri, localName, qName);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        invokeCustomHandlersMethod("characters", ch, start, length);
    }

    @Override
    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
        invokeCustomHandlersMethod("ignorableWhitespace", ch, start, length);
    }

    @Override
    public void processingInstruction(String target, String data) throws SAXException {
        invokeCustomHandlersMethod("processingInstruction", target, data);
    }

    @Override
    public void skippedEntity(String name) throws SAXException {
        invokeCustomHandlersMethod("skippedEntity", name);
    }

    public void setUp(List<String> params) {
        invokeCustomHandlersMethod("setUp", params);
    }

    public void addCustomHandler(Action custom) {
        if (custom != null) handlers.add(custom);
    }

    public void removeCustomHandler(Action custom) {
        if (custom != null) handlers.remove(custom);
    }
}
